package com.suning.sawp.in.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.I0Itec.zkclient.ZkClient;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.suning.framework.image.common.FtpEntity;
import com.suning.framework.image.common.FtpUtils;
import com.suning.framework.web.controller.BaseController;
import com.suning.sawp.constants.PromotionErrorConstants;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.sys.UserInfo;
import com.suning.sawp.exception.MobileException;
import com.suning.sawp.intf.sys.SystemService;
import com.suning.sawp.service.util.GsonUtils;
import com.suning.sawp.service.util.RedisCacheUtils;
import com.suning.vgs.follow.remote.intf.StoreManRemoteService;

@Controller
@RequestMapping("/cache")
public class CacheController extends BaseController implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(CacheController.class);

    @Resource
    RedisCacheUtils cacheUtils;

    @Autowired
    SystemService systemService;

    @Resource
    StoreManRemoteService storeManRemoteService;

    @Value("#{settingConfig[ftpAddress]}")
    String ftpAddress;

    @Value("#{settingConfig[ftpUserName]}")
    String ftpUserName;

    @Value("#{settingConfig[ftpPassword]}")
    String ftpPassword;

    @Value("#{settingConfig[localTempFileDirPath]}")
    String localTempFileDirPath;

    @Value("#{settingConfig[zkAddress]}")
    String zkAddress;
    
    private ZkClient zkClient;
    
    @ResponseBody
    @RequestMapping("/clearCache.do")
    public String clearCache(String key, String field) {
        if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(field)) {
            cacheUtils.clearCacheData(key, field);
            return "clear success";
        } else if (StringUtils.isNotBlank(key)) {
            cacheUtils.clearCacheData(key);
            return "clear success";
        }
        return "clear failed";
    }

    /**
     * 
     * 功能描述: 后台更新店员基础信息<br>
     * 〈功能详细描述〉
     *
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @ResponseBody
    @RequestMapping("/updateStoremanInfo.do")
    public String updateStoremanInfo(String staffId) {
        ReturnMsg<UserInfo> ret = new ReturnMsg<UserInfo>();
        try {
            ret = systemService.queryUserInfo(staffId);
        } catch (Exception e) {
            LOGGER.error("updateStoremanInfo FAIL，staffId=" + staffId, e);
            ret.setRetFlag(ReturnMsg.FAIL);
            ret.setErrorCode(PromotionErrorConstants.ACT_QUERY_ERR_E999);
            ret.setErrorMessage(
                    PromotionErrorConstants.ACT_QUERY_ERR_MAP.get(PromotionErrorConstants.ACT_QUERY_ERR_E999));
        }

        return ret.getRetFlag();
    }

    /**
     * 
     * 功能描述: 删除店员信息<br>
     * 〈功能详细描述〉
     *
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @ResponseBody
    @RequestMapping("/delStoreMan.do")
    public String delStoreMan(String staffId) {
        ReturnMsg<UserInfo> ret = new ReturnMsg<UserInfo>();
        try {
            storeManRemoteService.dealQuitStoreMan(staffId);
        } catch (Exception e) {
            LOGGER.error("delStoreMan FAIL，staffId=" + staffId, e);
            ret.setRetFlag(ReturnMsg.FAIL);
            ret.setErrorCode(PromotionErrorConstants.ACT_QUERY_ERR_E999);
            ret.setErrorMessage(
                    PromotionErrorConstants.ACT_QUERY_ERR_MAP.get(PromotionErrorConstants.ACT_QUERY_ERR_E999));
        }

        return ret.getRetFlag();
    }

    /**
     * 
     * 功能描述: 查询目录下的文件列表<br>
     * 〈功能详细描述〉
     *
     * @param dirPath
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @ResponseBody
    @RequestMapping("/biFtpFileList.do")
    public String ftpFileList(String dirPath) throws IOException {
        ReturnMsg<List<String>> retMsg = new ReturnMsg<List<String>>();
        FtpEntity ftpEntity = new FtpEntity(ftpAddress, ftpUserName, ftpPassword, null);
        FTPClient ftpClient = null;
        try {
            ftpClient = FtpUtils.borrowClient(ftpEntity);
            FTPFile[] files = ftpClient.listFiles(dirPath);
            List<String> list = new ArrayList<String>();
            for (FTPFile file : files) {
                list.add(file.getName());
            }
            retMsg.setData(list);
        } catch (Exception ex) {
            LOGGER.error("biFtpFileList.do", ex);
            if (null != ftpClient) {
                FtpUtils.returnBrokenClient(ftpClient);
                ftpClient = null;
            }
        } finally {
            if (ftpClient != null) {
                FtpUtils.returnClient(ftpClient);
            }
        }
        return GsonUtils.toJson(retMsg, false);
    }

    @RequestMapping("/biFileDownload.do")
    public void biFileDownload(String fileName, String dirPath, HttpServletResponse resp) {
        String ftpFilePath = dirPath + "/" + fileName;
        FtpEntity ftpEntity = new FtpEntity(ftpAddress, ftpUserName, ftpPassword, null);
        OutputStream os = null;
        FTPClient ftpClient = FtpUtils.borrowClient(ftpEntity);
        String remotePath = ftpEntity.getTemp();
        try {
            resp.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            os = resp.getOutputStream();
            if (remotePath != null) {
                if (!ftpClient.changeWorkingDirectory(removeStart(remotePath, "/"))) {
                    throw new MobileException("down file with error:" + remotePath + " can not enter");
                }
            }
            Boolean flag = ftpClient.retrieveFile(ftpFilePath, os);
            if (!flag) {
                throw new MobileException("down fail");
            }
        } catch (Exception e) {
            LOGGER.error("biFileDownload fail", e);
            FtpUtils.returnBrokenClient(ftpClient);
            ftpClient = null;
        } finally {
            if (ftpClient != null) {
                FtpUtils.returnClient(ftpClient);
            }
        }
    }

    private String removeStart(String str, String remove) {
        if (StringUtils.isEmpty(str) || StringUtils.isEmpty(remove)) {
            return str;
        }
        if (str.startsWith(remove)) {
            return str.substring(remove.length());
        }
        return str;
    }

    @RequestMapping("/biFileUpload.do")
    @ResponseBody
    public String biFileUpload(@RequestParam(value = "upfile", required = true) MultipartFile upfile, String dirPath,
            String fileName) throws IOException, Exception {
        ReturnMsg<String> retMsg = new ReturnMsg<String>();
        FtpEntity ftpEntity = new FtpEntity(ftpAddress, ftpUserName, ftpPassword, dirPath);
        try {
            FtpUtils.uploadFile(ftpEntity, "/" + fileName, upfile.getInputStream());
        } catch (Exception e) {
            LOGGER.error("biFileUpload error", e);
        }

        return GsonUtils.toJson(retMsg, false);
    }

    /**
     * 功能描述: 查询缓存<br>
     * 
     * @param key
     * @param field
     * @return
     */
    @RequestMapping("/queryCacheByKeyAndField.do")
    @ResponseBody
    public String queryCacheByKeyAndField(String key, String field) {
        String result = StringUtils.EMPTY;
        try {
            if (StringUtils.isNotBlank(field)) {
                result = cacheUtils.hget(key, field);
                LOGGER.info("hget key {} field{} success", new Object[] { key, field });
            } else {
                result = cacheUtils.get(key);
                LOGGER.info("get key {} success", new Object[] { key });
            }
        } catch (Exception e) {
            LOGGER.error("queryCacheByKeyAndField error", e);
        }
        return result;
    }

    /**
     * 功能描述: 查询set缓存<br>
     * 
     * @param key
     * @param field
     * @return
     */
    @RequestMapping("/querySetCacheByKey.do")
    @ResponseBody
    public String querySetCacheByKey(String key) {
        Set<String> result = new HashSet<String>();
        try {
            result = cacheUtils.smembers(key);
            LOGGER.info("querySetCacheByKey key {} success, value is {}", new Object[] { key, result.toString() });
        } catch (Exception e) {
            LOGGER.error("querySetCacheByKey error", e);
        }
        return result.toString();
    }

    /**
     * 功能描述: 查询key过期时间<br>
     * 
     * @param key
     * @param field
     * @return
     */
    @RequestMapping("/queryCacheKeyExpireTime.do")
    @ResponseBody
    public Long queryCacheKeyExpireTime(String key) {
        Long result = null;
        try {
            result = cacheUtils.ttl(key);
            LOGGER.info("queryCacheKeyExpireTime key {} success, ttl is {}", new Object[] { key, result });
        } catch (Exception e) {
            LOGGER.error("queryCacheKeyExpireTime error", e);
        }
        return result;
    }
    
    @RequestMapping("/queryZkList.do")
    @ResponseBody
    public String queryZkList(String path) {
        return getChilds(path);
    }
    
    @RequestMapping("/saveZk.do")
    @ResponseBody
    public String saveZk(String path, String node) {
        zkClient.writeData(path, node);
        return "1";
    }
    
    private String getChilds(String path){
        Assert.notNull(path);
        List<Map<String, String>> childs = new ArrayList<Map<String,String>>();
        List<String> children = zkClient.getChildren(path);
        if (CollectionUtils.isEmpty(children)) {
            Map<String, String> map = new HashMap<String, String>();
            String data = (String)zkClient.readData(path);
            map.put("id", path);
            map.put("data", "{}".equals(data) ? "" : data);
            childs.add(map);
        } else {
            for (String eachPath : children) {
                Map<String, String> map = new HashMap<String, String>();
                String pathPrefix = path.endsWith("/") ? path : path + "/";
                map.put("id", pathPrefix + eachPath);
                map.put("text", eachPath);
                map.put("pid", path);
                map.put("classes", "folder");
                map.put("hasChildren", zkClient.getChildren(pathPrefix + eachPath).isEmpty() ? "false" : "true");
                map.put("isNew", "false");
                try {
                    String data = (String)zkClient.readData(pathPrefix + eachPath);
                    map.put("data", "{}".equals(data) ? "" : data);
                } catch (Exception e) {
                }
                childs.add(map);
            }
        }
        
        
        return GsonUtils.toJson(childs);
    }
    
    private void initZkClient() {
        try {
            if (null != zkAddress) {
                zkClient = new ZkClient(zkAddress);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initZkClient();
    }
}